import re
from util import md5


class Element:

    def __init__(self, parent, payload):
        self.parent = parent
        self.children = {}
        self.payload = payload
        self._path = None

        if self.parent is not None:
            self.parent.add_child(self)

    def __getitem__(self, item):
        return self.payload[item]

    def __iter__(self):
        return iter(self.payload)

    def __str__(self):
        stream = "<Element:" + self.name
        if self.type is not None:
            stream += "," + self.type
        if self.text is not None:
            stream += "," + self.text

        return stream + ">"

    def __repr__(self):
        return str(self)

    def get(self, item, default=None):
        return self.payload.get(item, default)

    def add_child(self, child):
        if child.name not in self.children:
            self.children[child.name] = []
        self.children[child.name].append(child)

    def key(self):
        # 必须满足两个要求
        # 界面结构的改变，不影响key值的产生
        # # 列表的上下滑动，不影响同一个控件产生的key
        # 同类型的控件，需有不同的key值
        # # 列表中，相同但不同列的元素，需有不同的key值，对应各自
        return md5(self.path)

    def element(self, poco):
        kw = self._get_poco_kw()
        element = poco(self.name, **kw)

        l = len(element)
        if l == 1:
            return element
        elif l == 0:
            return None

        if self.parent is not None:
            parent = self.parent.element(poco)
            children = parent.child(self.name)

            def temp(x):
                t = re.findall("^.*\[(.+?)\]\"$", str(x))
                if t:
                    return int(t[0])
                return str(x)

            children = sorted(children, key=temp)

            index = self.self_index()
            if index is not None and len(children) > index:
                return children[index]
        else:
            return element[0]

    def index(self, child):
        if child.name not in self.children:
            return None
        return self.children[child.name].index(child)

    def _get_poco_kw(self):
        kw = {}
        if self.type is not None:
            kw["type"] = self.type
        if ":id/" not in self.name and self.text is not None:
            kw["text"] = self.text
        return kw

    @property
    def path(self):
        if self._path is None:
            parent_key = "/"
            local = self.local

            if self.parent is not None:
                parent_key = self.parent.path

            if local == 0:
                local = self.self_index() + 1
            self._path = parent_key + "/" + self.name + "_" + str(local)
        return self._path

    @property
    def name(self):
        return self.payload.get("name", "")

    @property
    def local(self):
        return self.payload.get("zOrders", {}).get("local", 0)

    @property
    def type(self):
        return self.payload.get("type", None)

    @property
    def text(self):
        return self.payload.get("text", None)

    def self_index(self):
        if self.parent is None:
            return 0
        return self.parent.index(self)


def walk_element(elements: dict, dump: dict, parent=None):
    element = Element(parent, dump["payload"])
    elements[element.key()] = element
    if "children" in dump:
        for data in dump["children"]:
            walk_element(elements, data, element)
